package base;

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedList;

/**
 * Gather all {@link Server}
 * 
 * @author rweiller
 * 
 */
public class Servers
{
	public ArrayList<Server>	list;
	public int					size;
	public int					output				= 0;

	public FileWriter			fstream;
	public BufferedWriter		out;
	public String				results;
	public String				results_complements;
	public static final String	RESULTS_INIT_STRING	= "input;output;server_id;lb_time;sv_time;total_time;weight\n";
	public static final String	RESULTS_INIT_COMPLEMENTS_STRING	= "server_id;times_empty_server;times_proceed_server;\n";

	public Servers(int nb_server, int process_power)
			throws IllegalArgumentException
	{
		if (nb_server < 1)
		{
			throw new IllegalArgumentException("Number of server < 1");
		}

		if (process_power < 1)
		{
			throw new IllegalArgumentException("Process power < 1");
		}

		size = nb_server;
		results = RESULTS_INIT_STRING;
		results_complements = RESULTS_INIT_COMPLEMENTS_STRING;

		list = new ArrayList<Server>();
		for (int i = 0; i < nb_server; i++)
		{
			list.add(new Server(i, process_power));
		}
	}

	/**
	 * Add an element in the specific server id.
	 * 
	 * @param id the id server.
	 * @param el the element.
	 */
	public void add(int id, Element el)
	{
		list.get(id).add(el);
	}

	public ArrayList<Server> getList()
	{
		return list;
	}

	/**
	 * 
	 * @return the biggest size server.
	 */
	public Server getMaxSizeServer()
	{
		Server server = list.get(0);
		for (Server sv : list)
		{
			if (sv.getList().size() > server.getList().size())
			{
				server = sv;
			}
		}
		return server;
	}

	/**
	 * 
	 * @return the more weight server.
	 */
	public Server getMaxWeightServer()
	{
		Server server = list.get(0);
		for (Server sv : list)
		{
			if (sv.getWeight() > server.getWeight())
			{
				server = sv;
			}
		}
		return server;
	}

	/**
	 * 
	 * @return the smallest size server.
	 */
	public Server getMinSizeServer()
	{
		Server server = list.get(0);
		for (Server sv : list)
		{
			if (sv.getList().size() < server.getList().size())
			{
				server = sv;
			}
		}
		return server;
	}

	/**
	 * 
	 * @return the less weight server.
	 */
	public Server getMinWeightServer()
	{
		Server server = list.get(0);
		for (Server sv : list)
		{
			if (sv.getWeight() < server.getWeight())
			{
				server = sv;
			}
		}
		return server;
	}

	/**
	 * 
	 * @return true if all servers are empty.
	 */
	public boolean isEmpty()
	{
		for (Server sv : list)
		{
			if (!sv.isEmpty())
				return false;
		}
		return true;
	}

	/**
	 * Foreach server, proceed to the calcul operation, also increment time for
	 * each Element of each server.
	 */
	public void proceed()
	{
		LinkedList<Element> list_element = null;
		int total_time_spent;
		for (Server sv : list)
		{
			if (sv.isEmpty())
			{
				continue;
			}
			else
			{
				sv.incElementTime();
				list_element = sv.proceed();
				for (Element el : list_element)
				{
					el.setOutput(output);
					output++;
					total_time_spent = el.getTimeLoadBalancer() + el.getTimeServer();
					results = results.concat(el.getInput() + ";" + el.getOutput() + ";" + el.getIdServer() + ";" + el.getTimeLoadBalancer() + ";" + el.getTimeServer() + ";" + total_time_spent + ";" + el.getBaseWeight() + ";\n");
				}
			}
		}
	}

	/**
	 * 
	 * @return the servers size.
	 */
	public int size()
	{
		return size;
	}

	/**
	 * Write results in this filename.
	 * 
	 * @param filename the emplacement filename.
	 * @throws IOException if this filename doesn't exits and can't create it.
	 */
	public void writeToFile(String filename) throws IOException
	{
		fstream = new FileWriter(filename);
		out = new BufferedWriter(fstream);
		out.write(results);
		out.close();
	}
	
	public void writeToFileComplements(String filename) throws IOException
	{
		int i = 0;
		for (Server sv : list)
		{
			results_complements = results_complements.concat(i + ";" + sv.getTimes_empty_server() + ";" + sv.getTimes_proceed_server() + ";\n");
			i++;
		}
		
		fstream = new FileWriter(filename);
		out = new BufferedWriter(fstream);
		out.write(results_complements);
		out.close();
	}
}
